from datetime import datetime
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType


class BaseModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True


class Note(BaseModel):
    """Pice of text to remember"""
    title = models.CharField(max_length=255, null=True, blank=True)
    body = models.TextField()

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()

    def __str__(self):
        return "<Note: {} {}>".format(self.object_id, self.content_object)


class Task(BaseModel):
    """Pice of work to be done"""
    UNPRIORITIZED = "Unprioritized"
    HIGHT = "Hight"
    MEDIUM = "Medium"
    LOW = "Low"

    PRIORITY_CHOICES = ((0, UNPRIORITIZED), (1, HIGHT), (2, MEDIUM), (3, LOW))

    title = models.CharField(max_length=255)
    description = models.TextField()
    due_date = models.DateTimeField(blank=True, null=True)
    priority = models.IntegerField(default=0, choices=PRIORITY_CHOICES)
    completed = models.BooleanField(blank=True)
    completed_at = models.DateTimeField(blank=True, null=True)
    notes = GenericRelation(Note)

    def __str__(self):
        return "<Task: {} {} {}>".format(self.title, self.due_date, self.priority)


class Plan(BaseModel):
    """Handle tasks together"""
    title = models.CharField(max_length=255)
    goal = models.CharField(max_length=255)
    tasks = models.ManyToManyField(Task)
    
    def __str__(self):
        return "<Plan: {}>".format(self.title)


class Issue(BaseModel):
    """Anything that stops you from moving forward"""
    title = models.CharField(max_length=255, null=True, blank=True)
    description = models.TextField()
    mitigation = models.TextField()

    def __str__(self):
        return "<Issue: {}>".format(self.title)


class Project(BaseModel):
    """Keep track personal (and not so) projects"""
    title = models.CharField(max_length=255)
    description = models.TextField()
    reason = models.TextField()  # Reason to spent any time on that; what's the benefit?
    plans = models.ManyToManyField(Plan)
    notes = GenericRelation(Note)

    def __str__(self):
        return "<Project: {}>".format(self.title)


class Material(BaseModel):
    """Data to be processed (tarbals, csv files..)""" 
    title = models.CharField(max_length=255)
    file = models.FileField()
    notes = GenericRelation(Note)

    def __str__(self):
        return "<Material: {}>".format(self.title)


class Book(BaseModel):
    """Keep track of your books"""
    title = models.CharField(max_length=255)
    author = models.CharField(max_length=255, blank=True, null=True)
    scale = models.PositiveIntegerField()
    position = models.PositiveIntegerField()
    notes = GenericRelation(Note)
    resume = models.TextField(blank=True, null=True)
    completed = models.BooleanField(blank=True)
    completed_at = models.DateTimeField(blank=True, null=True)
    materials = models.ForeignKey(Material, blank=True, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return "<Book: {} {} {}>".format(self.title, self.author, self.position)


class BookStackRecord(BaseModel):
    """Represent books in the stack."""
    position = models.PositiveIntegerField()
    book = models.OneToOneField(Book, on_delete=models.SET_NULL, null=True)
    
    def __str__(self):
        return "<BookStackRecord: {}>".format(self.position)


class Course(BaseModel):
    """Educational course"""
    title = models.CharField(max_length=255)
    info = models.TextField(max_length=255)
    reason = models.TextField()
    link = models.URLField()
    progress = models.PositiveIntegerField()
    completed = models.BooleanField(blank=True)
    completed_at = models.DateTimeField(blank=True, null=True)
    materials = models.ForeignKey(Material, blank=True, null=True, on_delete=models.CASCADE)
    notes = GenericRelation(Note)

    def __str__(self):
        return "<Course: {}: {}>".format(self.title, self.progress)


class CourseStackRecord(BaseModel):
    """Represent course in the stack."""
    position = models.PositiveIntegerField()
    course = models.OneToOneField(Course, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return "<CourseStackRecord: {}>".format(self.position)



class PersonOfInterest(BaseModel):
    """Book authors, bloggers, coders, journalists to whatch"""
    name = models.CharField(max_length=255)
    notes = GenericRelation(Note)

    def __str__(self):
        return self.name


class Story(BaseModel):
    """Day-to-day writings lie here"""

    name = models.CharField(max_length=255, default=datetime.now())
    content = models.TextField()

    def __str__(self):
        return "<Story: {} {}>".format(self.name, self.created_at)


class Timeline(models.Model):
    """Represent time in chunks of 52 weeks"""
    

class Week(models.Model):
    """To track goals, progress and tasks"""
    number = models.PositiveIntegerField()
    start_date = models.DateField()
    end_date = models.DateField()

    goal = models.CharField(max_length=255)
    summary = models.TextField(blank=True, null=True)
    year = models.PositiveIntegerField(default=datetime.today().year)

    def __str__(self):
        return "<Week: {} - {}>".format(self.number, self.goal)


class Site(BaseModel):
    """Sites I'm registered in"""
    # TODO: add relation from `notes' -- allow create some kind of comments\notes
    # about something from site (interesting posts, receips)..
    # Schedule events basing on site urls

    RANK_CHOICES = (
        (1, 'Superb'),
        (2, 'Good'),
        (3, 'Bad'),
        (4, 'Aweful')
    )
    name = models.CharField(max_length=255)
    url = models.URLField(max_length=300)
    description = models.TextField(blank=True, null=True)
    rank = models.PositiveIntegerField(choices=RANK_CHOICES, default=0)

    def __str__(self):
        return "<Site: {}>".format(self.name)
